import wx
import os
import shutil
import subprocess
import thread
import sys
import wx.stc as stc
from xml.sax import make_parser, SAXException

import IDE_dialog_authentication
import IDE_texteditor

import pysvn

class ProjectManager(wx.TreeCtrl):
	def __init__(self, parent, id, controller):
		wx.TreeCtrl.__init__(self, parent, id)

		self.IDE = controller
		self.ProjectLoaded = False
		self.ProjectPath = None
		self.ProjectDirectories = None
		self.ProjectSettings = dict()
		self.SVNCurrentAction = None
		self.SVNClient = pysvn.Client()
		self.SVNClient.exception_style = 1
		self.SVNClient.callback_notify = self.__SVNClient_Callback_Notify
		self.SVNClient.callback_get_login = self.__SVNClient_Callback_GetLogin
		self.SVNClient.callback_ssl_server_trust_prompt = self.__SVNClient_Callback_SSLTrustPrompt

		self.Bind(wx.EVT_TREE_ITEM_RIGHT_CLICK, self.__ShowContextMenu)

########################################### PROJECT FUNCTIONS ######################################

	def OnActivate(self, event):
		node = event.GetItem()
		path = self.GetPyData(node)
			
		if (self.__CheckIsFileOpen(path) != -1):
			return;

		try:
			# Open the file through Subversion
			file = open(path, 'r')
			text = file.read()
			file.close()
			# Get the wxWindow for the current tab, get the first child (textarea)
			self.IDE.notebook.AddPage(IDE_texteditor.TextEditor(self.IDE.notebook, 1000, '', 1), os.path.basename(path), select = 1)
			c = self.IDE.notebook.GetPage(self.IDE.notebook.GetSelection())
			c.ClearAll()
			c.AddText(text)
			c.SetLexer(stc.STC_LEX_NULL)
			
			# Detect appropriate Lexer to use
			ext = os.path.splitext(os.path.basename(path))[1].lower()
			if (ext == ".py"):
				c.SetLexer(stc.STC_LEX_PYTHON)
			if (ext == ".lua"):
				c.SetLexer(stc.STC_LEX_LUA)
			if (ext == ".pl"):
				c.SetLexer(stc.STC_LEX_PERL)
			if (ext == ".conf"):
				c.SetLexer(stc.STC_LEX_CONF)
			if (ext == ".c" or ext == ".h" or ext == ".cc" or ext == ".hpp" or ext == ".cpp"):
				c.SetLexer(stc.STC_LEX_CPP)
			if (ext == ".diff"):
				c.SetLexer(stc.STC_LEX_DIFF)
			if (ext == ".htm" or ext == ".html"):
				c.SetLexer(stc.STC_LEX_HTML)
			if (ext == ".php" or ext == ".phps"):
				c.SetLexer(stc.STC_LEX_PHP)
			if (ext == ".rb"):
				c.SetLexer(stc.STC_LEX_RUBY)
			if (ext == ".sql"):
				c.SetLexer(stc.STC_LEX_SQL)
			
			#c.StyleAllLines(self.IDE.taskman, path)
			c.path = path
			self.IDE.notebook.SetPageText(self.IDE.notebook.GetSelection(),os.path.basename(path))
			c.modified = False
			wx.CallLater(100,c.AllowSaveMark)
			self.IDE.menumanager.FileOpened()
			
			pass
		except IOError, error:
			dlg = wx.MessageDialog(self.IDE, 'Error opening file ' + str(error))
			dlg.ShowModal()
		except UnicodeDecodeError, error:
			dlg = wx.MessageDialog(self.IDE, 'Error opening file ' + str(error))
			dlg.ShowModal()

	def OnPageClose(self, event):
		self.IDE.menumanager.FileClosed()
		if not self.AskSaveFile():
			event.Skip()

	def NewProject(self):
		dlg = wx.DirDialog(self, "Choose a directory for the new Subversion project:",
						style=wx.DD_DEFAULT_STYLE
						#| wx.DD_DIR_MUST_EXIST
						#| wx.DD_CHANGE_DIR
						)
		
		# If the user selects OK...
		if dlg.ShowModal() == wx.ID_OK:
			
			# Check if a project already exists here...
			if (os.path.exists(os.path.join(dlg.GetPath(),"settings.spy"))):
				dlg = wx.MessageDialog(self.IDE, "A project already exists in this directory.","Error",wx.OK)
				dlg.ShowModal()
				self.NewProject()
				return 0
			
			repodir = dlg.GetPath()
			
			# Get the repository name..
			dlg = wx.TextEntryDialog(
				self.IDE, 'Enter the repository nickname:',
				'Repository Name', 'My Subversion Repository')

			if not (dlg.ShowModal() == wx.ID_OK):
				return 0
			else:
				reponame = dlg.GetValue()
				
			# Get the repository URL..
			dlg = wx.TextEntryDialog(
				self.IDE, 'Enter the repository URL:',
				'Repository URL', 'http://www.server.com/my_repo_name')

			if not (dlg.ShowModal() == wx.ID_OK):
				return 0
			else:
				repourl = dlg.GetValue()
			
			# Create the project then..
			self.__NewProject(repodir,repourl,reponame)
			
		
		return 0

	def LoadProject(self):
		dlg = wx.DirDialog(self, "Choose a directory to load the Subversion project from:",
						style=wx.DD_DEFAULT_STYLE
						#| wx.DD_DIR_MUST_EXIST
						#| wx.DD_CHANGE_DIR
						)
		
		# If the user selects OK...
		if dlg.ShowModal() == wx.ID_OK:
			
			# Check if a project already exists here...
			if not (os.path.exists(os.path.join(dlg.GetPath(),"settings.spy"))):
				dlg = wx.MessageDialog(self.IDE, "There is no project located in this directory.","Error",wx.OK)
				dlg.ShowModal()
				self.NewProject()
				return 0
			
			# Create the project then..
			self.__LoadProject(dlg.GetPath())
			
		return 0

	def SaveProject(self):
		self.__SaveProject()
		return 0

	def CloseProject(self):
		self.__CloseProject()
		return 0

########################################### ADD XXXXXX FUNCTIONS ######################################

	def AddScript(self):
		return 0

	def AddExisting(self):
		return 0

	def AddExtension(self):
		return 0

########################################### FILE MANAGEMENT FUNCTIONS ######################################

	def SaveFile(self):
		self.__SaveFile()

	def SaveFileAs(self):
		self.__SaveFileAs()

	def SaveAllFiles(self):
		self.__SaveAllFiles(False)

	def NewFile(self):
		self.IDE.notebook.AddPage(IDE_texteditor.TextEditor(self.IDE.notebook, 1000, '', 1), "New File", select = 1)
		c = self.IDE.notebook.GetPage(self.IDE.notebook.GetSelection())
		c.ClearAll()
		c.path = False
		c.modified = False
		wx.CallLater(100,c.AllowSaveMark)
		self.IDE.menumanager.FileOpened()

	def AskSaveFile(self):
		return self.__SaveAskFile()

	def CloseFile(self):
		self.IDE.menumanager.FileClosed()
		if self.IDE.projectman.AskSaveFile() != 1:
			self.IDE.notebook.DeletePage(self.IDE.notebook.GetSelection())

	def CloseAllFiles(self):
		for i in range(self.IDE.notebook.GetPageCount()):
			if self.__SaveAskFile() == 1:
				# Cancel
				return 0
			else:
				self.IDE.notebook.DeletePage(self.IDE.notebook.GetSelection())

########################################### SVN NOTIFY FUNCTIONS ####################################

	def __SVNClient_Callback_Notify(self,event_dict):
		if (event_dict["action"] == pysvn.wc_notify_action.update_completed and self.SVNCurrentAction == "LoadingProject"):
			# Get the icon files first
			self.__icons_isz = (16,16)
			self.__icons_il = wx.ImageList(self.__icons_isz[0], self.__icons_isz[1])
			self.__icons_fldridx	 	= 	self.__icons_il.Add(wx.ArtProvider_GetBitmap(wx.ART_FOLDER,	  wx.ART_OTHER, self.__icons_isz))
			self.__icons_fldropenidx = 		self.__icons_il.Add(wx.ArtProvider_GetBitmap(wx.ART_FILE_OPEN,   wx.ART_OTHER, self.__icons_isz))
			self.__icons_fileidx	 	= 	self.__icons_il.Add(wx.ArtProvider_GetBitmap(wx.ART_NORMAL_FILE, wx.ART_OTHER, self.__icons_isz))
			self.SetImageList(self.__icons_il)
			
			# Scan for the files in the checkout directory and put them into the project data
			directories = dict()
			root_node = self.AddRoot(self.ProjectSettings["RepositoryName"])
			self.root = root_node
			self.SetPyData(root_node, os.path.join(self.ProjectPath,"checkout"))
			self.SetItemImage(root_node, self.__icons_fldridx, wx.TreeItemIcon_Normal)
			self.SetItemImage(root_node, self.__icons_fldropenidx, wx.TreeItemIcon_Expanded)
			
			for root, dirs, files in os.walk(os.path.join(self.ProjectPath,"checkout")):
				dirroot = root[len(os.path.join(self.ProjectPath,"checkout")):]
				if (len(dirroot) > 1):
					dirroot = dirroot[1:]
				
				if (dirroot.startswith(".svn" + os.sep) or dirroot.count(os.sep + ".svn") > 0 or dirroot == ".svn"):
					# We want to skip the SVN directory
					continue
				
				# We need to split the root path name to locate the nodes to search for
				if dirroot == "":
					pnode = root_node
				else:
					pnode = directories[dirroot]
						
				# We're at the node we need to insert at
				for i in dirs:
					if not (i == ".svn"):
						# Only add if we aren't an .svn child
						node = self.AppendItem(pnode, i)
						self.SetPyData(node, os.path.join(root,i))
						self.SetItemImage(node, self.__icons_fldridx, wx.TreeItemIcon_Normal)
						self.SetItemImage(node, self.__icons_fldropenidx, wx.TreeItemIcon_Expanded)
						directories[os.path.join(dirroot,i)] = node
				for i in files:
					fnode = self.AppendItem(pnode, i)
					self.SetPyData(fnode, os.path.join(root,i))
					self.SetItemImage(fnode, self.__icons_fileidx, wx.TreeItemIcon_Normal)
			
			self.ProjectDirectories = directories
			
			self.ExpandAll()
			
			self.IDE.SubversionLog("   Completed.")
			
		elif (event_dict["action"] == pysvn.wc_notify_action.commit_modified or event_dict["action"] == pysvn.wc_notify_action.commit_added):
			if (self.SVNCurrentAction == "SaveAllFiles"):
				if (self.__total_repo_files == self.__count_repo_files):
					self.IDE.SubversionLog("   Completed.")
				else:
					self.__count_repo_files += 1
			elif (self.SVNCurrentAction == "SaveFile"):
				self.IDE.SubversionLog("   Completed.")
			elif (self.SVNCurrentAction == "AddFile"):
				self.IDE.SubversionLog("   Completed.")
			elif (self.SVNCurrentAction == "RenameFile"):
				self.SetItemText(self.__repo_rename_node,self.__repo_rename_destname)
				self.IDE.SubversionLog("   Completed.")
			elif (self.SVNCurrentAction == "MoveFile"):
				self.Delete(self.__repo_move_delnode)
				# Now create a new node
				fnode = self.AppendItem(self.__repo_rename_destparentnode, self.__repo_move_text)
				self.SetPyData(fnode, self.__repo_move_path)
				self.SetItemImage(fnode, self.__icons_fileidx, wx.TreeItemIcon_Normal)
				self.Update()
				self.IDE.SubversionLog("   Completed.")
		
		elif (event_dict["action"] == pysvn.wc_notify_action.commit_deleted):
			if (self.SVNCurrentAction == "DeleteFile"):
				self.Delete(self.__repo_delete_node)
				self.Update()
				self.IDE.SubversionLog("   Completed.")
	
	def __SVNClient_Callback_GetLogin(self,realm, username, may_save):
		dlg = IDE_dialog_authentication.LoginDialog(self.IDE, -1, "Authentication Required", True, "HTTPS")
		if (dlg.ShowModal() == wx.ID_OK):
			user = dlg.UsernameBox.GetValue()
			password = dlg.PasswordBox.GetValue()
			dlg.Destroy()
			return True, user, password, True
		pass
	
	def __SVNClient_Callback_SSLTrustPrompt(self,trust_dict):
		dlg = IDE_dialog_authentication.SSLTrustPromptDialog(self.IDE, -1, "SSL Prompt", trust_dict["hostname"], trust_dict["realm"])
		if (dlg.ShowModal() == wx.ID_YES):
			dlg.Destroy()
			return True, 0, True
		pass

########################################### INTERNAL FUNCTIONS ######################################

	def __NewProject(self,path,repository, repository_name):
		self.IDE.SubversionLog("Creating new project file...")
		try:
			os.mkdir(os.path.join(path,"checkout"))
		except IOError:
			noonecares = True
		except:
			self.IDE.SubversionLog("   Failed.")
			dlg = wx.MessageDialog(self.IDE, "Unable to create project checkout directory!","Error",wx.OK)
			dlg.ShowModal()
			return 0

		self.ProjectPath = path
		fname = os.path.join(path,"settings.spy")
		file = open(fname,'w')
		file.write('RepositoryName ' + repository_name + '\n')
		file.write('Repository ' + repository + '\n')
		file.close()
		self.IDE.SubversionLog("   Completed.")

		# Finally, load the project
		self.__LoadProject(path)
		
		return 0

	def __LoadProject(self,path):
		self.IDE.SubversionLog("Loading project file...")
		self.DeleteAllItems()
		self.ProjectDirectories = None
		
		# Check for settings file
		if not (os.path.exists(os.path.join(path,"settings.spy"))):
			self.IDE.SubversionLog("   Failed.")
			dlg = wx.MessageDialog(self.IDE, "Unable to locate settings.spy in the project directory!","Error",wx.OK)
			dlg.ShowModal()
			return 0

		# Load the settings
		self.ProjectSettings = dict()
		file = open(os.path.join(path,"settings.spy"),'r')
		settings = dict()
		line = file.readline()
		while not (line == ""):
			loc = line.find(" ")
			if not (loc == -1):
				part = line.partition(" ")
				settings[part[0]] = part[2].rstrip("\n")
			line = file.readline()
		file.close()
		
		# The variables settings now contains a list of settings
		repository_name = settings["RepositoryName"]
		repository = settings["Repository"]
		
		self.IDE.SubversionLog("   Completed.")
		self.IDE.SubversionLog("Checking out repository...")
		
		self.ProjectPath = path
		# The following doesn't work while the application running for some reason (Access Denied)
		#if (os.path.exists(os.path.join(self.ProjectPath,"checkout"))):
		#	# Make sure we clean the checkout directory first
		#	for root, dirs, files in os.walk(os.path.join(self.ProjectPath,"checkout"), topdown=False):
		#		for name in files:
		#			os.remove(os.path.join(root, name))
		#		for name in dirs:
		#			os.rmdir(os.path.join(root, name))
		self.ProjectSettings = settings
		self.SVNCurrentAction = "LoadingProject"
		try:
			self.SVNClient.checkout(repository + '/trunk',
					os.path.join(path,"checkout"))
		except pysvn._pysvn_2_6.ClientError, errordata:
			if (len(errordata.args) == 1):
				# We just have a plaintext error
				self.IDE.SubversionLog("   Failed.")
				dlg = wx.MessageDialog(self.IDE, "Subversion returned: " + errordata.args[0],"Error",wx.OK)
				dlg.ShowModal()
				return 0
			elif (len(errordata.args) == 2):
				print(errordata.args[0])
				if (errordata.args[1][0][1] == 170000):
					# Probably couldn't find the /trunk directory
					self.IDE.SubversionLog("   Failed.")
					dlg = wx.MessageDialog(self.IDE, "I couldn't connect to the Subversion repository.  Make sure that your repository has a /trunk folder, as this is where SubPython does all it's operations.","Error",wx.OK)
					dlg.ShowModal()
					return 0
				else:
					self.IDE.SubversionLog("   Failed.")
					dlg = wx.MessageDialog(self.IDE, "Subversion returned: " + errordata.args[0],"Error",wx.OK)
					dlg.ShowModal()
					return 0
			else:
				self.IDE.SubversionLog("   Failed.")
				dlg = wx.MessageDialog(self.IDE, "Subversion returned an unknown error.","Error",wx.OK)
				dlg.ShowModal()
				return 0
		
		self.IDE.menumanager.ProjectOpened()
		
		return None

	def __CloseProject(self):
		if (self.__SaveAllFiles() == 1):
			# They pressed Cancel
			return 0
		dlg = wx.MessageDialog(self.IDE, 'Save changes to project?',
							   'Save Changes',
							   wx.YES_NO | wx.NO_DEFAULT | wx.CANCEL | wx.ICON_INFORMATION
							   )
		result = dlg.ShowModal()
		if (result == wx.ID_YES):
			# Save Changes
			self.__SaveProject()
		if (result == wx.ID_CANCEL):
			# Cancel
			return 0
		self.DeleteAllItems()
		os.removedirs(os.path.join(self.ProjectPath,"checkout"))
		self.ProjectDirectories = None
		self.IDE.menumanager.ProjectClosed()
		for i in range(self.IDE.notebook.GetPageCount()):
			self.IDE.notebook.DeletePage(self.IDE.notebook.GetSelection())
		self.ProjectLoaded = False

	def __SaveAllFiles(self,prompt=True):
		count = self.IDE.notebook.GetPageCount()
		self.IDE.SubversionLog("Saving files to local disk...")
		repofiles = [];
		for i in range(count):
			# Loop through each page, check if it's modified, and ask to save changes.  Cancel should
			# make us return 1.
			path = self.IDE.notebook.GetPage(i).path
			modified = self.IDE.notebook.GetPage(i).modified
			if modified:
				if prompt:
					dlg = wx.MessageDialog(self.IDE, 'Save changes to ' + os.path.basename(path) + '?',
							   'Save Changes',
							   wx.YES_NO | wx.NO_DEFAULT | wx.CANCEL | wx.ICON_INFORMATION
							   )
					result = dlg.ShowModal()
				else:
					result = wx.ID_YES
				if (result == wx.ID_YES):
					# Save Changes
					try:
						if not path:
							# Check to see if path is set.  If not, prompt for filename.
							wcd = 'All Files (*.*)|*.*'
							save_dlg = wx.FileDialog(self, message='Save file as...', defaultDir=self.ProjectPath, defaultFile='', wildcard=wcd, style=wx.SAVE | wx.OVERWRITE_PROMPT)
							if save_dlg.ShowModal() == wx.ID_OK:
								path = save_dlg.GetPath()
							else:
								# Cancel
								return 1
						# Append to the list of repo files to submit
						repofiles.append(path)
						# Actually save the file..
						file = open(path, 'w')
						text = self.IDE.notebook.GetPage(i).GetText()
						file.write(text)
						file.close()
						
						self.IDE.SubversionLog("   Completed " + os.path.basename(path) + ".")
						
						self.IDE.notebook.GetPage(i).modified = False
						self.IDE.notebook.SetPageText(i,os.path.basename(path))
					except IOError, error:
						self.IDE.SubversionLog("   Failed " + os.path.basename(path) + ".")
						dlg = wx.MessageDialog(self.IDE, "Error saving " + os.path.basename(path) + ".")
						dlg.ShowModal()
				if (result == wx.ID_CANCEL):
					# Cancel
					return 1
		
		# Now update the repository
		self.SVNCurrentAction = "SaveAllFiles"
		self.__total_repo_files = len(repofiles)
		self.__count_repo_files = 1
		self.IDE.SubversionLog("Saving files to repository...")
		self.SVNClient.checkin(repofiles,"Updated file via SubPython")
		
		return 0

	def __SaveFile(self):
		# Check for modifications - if none, skip
		i = self.IDE.notebook.GetSelection()
		if not (self.IDE.notebook.GetPage(i).modified):
			return False
		
		path = self.IDE.notebook.GetPage(i).path
		if not path:
			self.IDE.SubversionLog("Saving file to local disk...")
			self.__SaveFileAs()
		else:
			self.IDE.SubversionLog("Saving " + os.path.basename(path) + " to local disk...")
			try:	
				modified = self.IDE.notebook.GetPage(i).modified
				file = open(path, 'w')
				text = self.IDE.notebook.GetPage(i).GetText()
				file.write(text)
				file.close()
				
				self.IDE.SubversionLog("   Completed.")
				self.SVNCurrentAction = "SaveFile"
				self.IDE.SubversionLog("Saving " + os.path.basename(path) + " to repository...")
				self.SVNClient.checkin([path],"Updated file via SubPython")
				
				self.IDE.notebook.GetPage(i).modified = False
				self.IDE.notebook.SetPageText(i,os.path.basename(path))
			except IOError, error:
				self.IDE.SubversionLog("   Failed.")
				dlg = wx.MessageDialog(self.IDE, "Error saving " + os.path.basename(path) + ".","Error",wx.OK)
				dlg.ShowModal()

	def __SaveFileAs(self):
		i = self.IDE.notebook.GetSelection()
		# Check to see if path is set.  If not, prompt for filename.
		wcd = 'All Files (*.*)|*.*'
		save_dlg = wx.FileDialog(self, message='Save file as...', defaultDir=os.path.join(self.ProjectPath,"checkout"), defaultFile='', wildcard=wcd, style=wx.SAVE | wx.OVERWRITE_PROMPT)
		if save_dlg.ShowModal() == wx.ID_OK:
			path = save_dlg.GetPath()
		else:
			# Cancel
			return 1
		try:
			modified = self.IDE.notebook.GetPage(i).modified
			file = open(path, 'w')
			text = self.IDE.notebook.GetPage(i).GetText()
			file.write(text)
			file.close()
			
			self.IDE.SubversionLog("Adding " + os.path.basename(path) + " to repository...")
			try:
				self.SVNClient.add(path)
				self.IDE.SubversionLog("   Completed.")
			except error:
				self.IDE.SubversionLog("   Failed.")
				return 0
			
			# Add the file to the tree
			if not (path[len(os.path.join(self.ProjectPath,"checkout"))+1:-len(os.path.basename(path))] == ""):
				if not (self.ProjectDirectories[path[len(os.path.join(self.ProjectPath,"checkout"))+1:-len(os.path.basename(path))]] == None):
					pnode = self.ProjectDirectories[path[len(os.path.join(self.ProjectPath,"checkout"))+1:-len(os.path.basename(path))]]
					fnode = self.AppendItem(pnode, os.path.basename(path))
					self.SetPyData(fnode, os.path.join(os.path.join(self.ProjectPath,"checkout"),os.path.basename(path)))
					self.SetItemImage(fnode, self.__icons_fileidx, wx.TreeItemIcon_Normal)
			else:
				pnode = self.root
				fnode = self.AppendItem(pnode, os.path.basename(path))
				self.SetPyData(fnode, os.path.join(os.path.join(self.ProjectPath,"checkout"),os.path.basename(path)))
				self.SetItemImage(fnode, self.__icons_fileidx, wx.TreeItemIcon_Normal)
			
			self.SVNCurrentAction = "AddFile"
			self.IDE.SubversionLog("Saving " + os.path.basename(path) + " to repository...")
			self.SVNClient.checkin([path],"Added file via SubPython")
			
			self.IDE.notebook.GetPage(i).modified = False
			self.IDE.notebook.SetPageText(i,os.path.basename(path))
		except IOError, error:
			self.IDE.SubversionLog("   Failed.")
			dlg = wx.MessageDialog(self.IDE, "Error saving " + os.path.basename(path) + ".","Error",wx.OK)
			dlg.ShowModal()

	def __SaveAskFile(self):
		i = self.IDE.notebook.GetSelection()
		# Ask to save the current file
		path = self.IDE.notebook.GetPage(i).path
		modified = self.IDE.notebook.GetPage(i).modified
		if modified:
			dlg = wx.MessageDialog(self.IDE, 'Save changes to ' + os.path.basename(path) + '?',
						   'Save Changes',
						   wx.YES_NO | wx.NO_DEFAULT | wx.CANCEL | wx.ICON_INFORMATION
						   )
			result = dlg.ShowModal()
			if (result == wx.ID_YES):
				# Save Changes
				try:
					if not path:
						# Check to see if path is set.  If not, prompt for filename.
						save_dlg = wx.FileDialog(self, message='Save file as...', defaultDir=dir, defaultFile='', wildcard=wcd, style=wx.SAVE | wx.OVERWRITE_PROMPT)
						if save_dlg.ShowModal() == wx.ID_OK:
							path = save_dlg.GetPath()
						else:
							# Cancel
							return 1
					file = open(path, 'w')
					text = self.IDE.notebook.GetPage(i).GetText()
					file.write(text)
					file.close()
					self.IDE.notebook.GetPage(i).modified = False
					self.IDE.notebook.SetPageText(i,os.path.basename(path))
				except IOError, error:
					dlg = wx.MessageDialog(self.IDE, "Error saving " + os.path.basename(path) + ".")
					dlg.ShowModal()
			if (result == wx.ID_CANCEL):
				# Cancel
				return 1
		return 0

	def __SaveProject(self):
		# Save the project settings
		file = open(os.path.join(self.ProjectPath,"settings.spy"),'w')
		for k, v in self.ProjectSettings:
			file.write(k + " " + v + '\n')
		file.close()

	def __AddFile(self,filename):
		# filename is relative to project data_location
		self.__SaveProject()

	def __RefreshStyling(self):
		# Runs through all the open files and resets all their styling.
		total = self.IDE.notebook.GetPageCount()
		i = 0
		while i < total:
			self.IDE.notebook.GetPage(i).ResetStyles()
			self.IDE.notebook.GetPage(i).StyleAllLines(self.IDE.taskman, self.IDE.notebook.GetPage(i).path)
			i += 1

	def CheckIsFileOpen(self, path):
		return self.__CheckIsFileOpen(path);

	def CheckIsFileOpenByTreeNode(self, node):
		path = self.GetPyData(node)
		return not self.__CheckIsFileOpen(path);

	def __CheckIsFileOpen(self, path):
		# Focuses the tab with the path if it is already open (and returns it's ID), or returns -1
		total = self.IDE.notebook.GetPageCount()
		i = 0
		while i < total:
			c1 = self.IDE.notebook.GetPage(i).path
			c2 = path
##			c1.replace("\\","/")
##			c1.replace("/./","/")
##			c1.replace("\\","/")
##			c1.replace("/./","/")
			if (c1 == c2):
				self.IDE.notebook.SetSelection(i)
				return i
			i += 1
		return -1

	def __ShowContextMenu(self, event):
		currentMenuItem = event.GetItem()
		self.SelectItem(currentMenuItem)
		if (not currentMenuItem.IsOk()):
			return 0
		
		# Work out what to do with this item
		if (currentMenuItem == self.root):
			# This object is the root node (repository management)
			popup_Sync = wx.NewId()

			#popup_ViewUsers = wx.NewId()
			popup_Properties = wx.NewId()
			
			self.Bind(wx.EVT_MENU, self.__ContextMenu_PropertiesRepo, id=popup_Properties)
			self.Bind(wx.EVT_MENU, self.__ContextMenu_SyncRepo, id=popup_Sync)
			
			menu = wx.Menu()
			menu.Append(popup_Sync, "Syncronize Entire Repository")
			menu.AppendSeparator()
			#menu.Append(popup_ViewUsers, "View Connected Users")
			menu.Append(popup_Properties, "Repository Properties")
			self.PopupMenu(menu)
			menu.Destroy()
		elif (self.GetChildrenCount(currentMenuItem,False) == 0):
			# This object is a file
			popup_DeterminePending = wx.NewId()
			popup_Commit = wx.NewId()
			popup_Revert = wx.NewId()

			popup_Lock = wx.NewId()
			popup_Unlock = wx.NewId()

			popup_Rename = wx.NewId()
			popup_Move = wx.NewId()
			popup_Delete = wx.NewId()
			
			self.Bind(wx.EVT_MENU, self.__ContextMenu_DeterminePendingFile, id=popup_DeterminePending)
			self.Bind(wx.EVT_MENU, self.__ContextMenu_CommitFile, id=popup_Commit)
			self.Bind(wx.EVT_MENU, self.__ContextMenu_RevertFile, id=popup_Revert)
			self.Bind(wx.EVT_MENU, self.__ContextMenu_DeleteFile, id=popup_Delete)
			self.Bind(wx.EVT_MENU, self.__ContextMenu_RenameFile, id=popup_Rename)
			self.Bind(wx.EVT_MENU, self.__ContextMenu_MoveFile, id=popup_Move)
			self.Bind(wx.EVT_MENU, self.__ContextMenu_LockFile, id=popup_Lock)
			self.Bind(wx.EVT_MENU, self.__ContextMenu_UnlockFile, id=popup_Unlock)
			
			menu = wx.Menu()
			menu.Append(popup_DeterminePending, "Determine Pending Changes")
			menu.Append(popup_Commit, "(Save and) Commit Changes")
			menu.Append(popup_Revert, "Revert Changes")
			if not (self.CheckIsFileOpenByTreeNode(currentMenuItem)):
				menu.Enable(popup_DeterminePending,False)
				menu.Enable(popup_Commit,False)
				menu.Enable(popup_Revert,False)
			menu.AppendSeparator()
			menu.Append(popup_Lock, "Lock File")
			menu.Append(popup_Unlock, "Unlock File")
			menu.AppendSeparator()
			menu.Append(popup_Rename, "Rename")
			menu.Append(popup_Move, "Move")
			menu.Append(popup_Delete, "Delete")
			self.PopupMenu(menu)
			menu.Destroy()
		else:
			# This object is a folder
			popup_DeterminePending = wx.NewId()
			popup_RefreshDirectory = wx.NewId()
			
			popup_AddFile = wx.NewId()
			
			popup_Rename = wx.NewId()
			popup_Move = wx.NewId()
			popup_Delete = wx.NewId()
			
			self.Bind(wx.EVT_MENU, self.__ContextMenu_DeterminePendingFolder, id=popup_DeterminePending)
			self.Bind(wx.EVT_MENU, self.__ContextMenu_RefreshDirectoryFolder, id=popup_RefreshDirectory)
			self.Bind(wx.EVT_MENU, self.__ContextMenu_AddFileFolder, id=popup_AddFile)
			self.Bind(wx.EVT_MENU, self.__ContextMenu_DeleteFolder, id=popup_Delete)
			self.Bind(wx.EVT_MENU, self.__ContextMenu_RenameFolder, id=popup_Rename)
			self.Bind(wx.EVT_MENU, self.__ContextMenu_MoveFolder, id=popup_Move)
			
			menu = wx.Menu()
			menu.Append(popup_DeterminePending, "Determine Pending Changes")
			menu.Append(popup_RefreshDirectory, "Refresh Directory List")
			menu.AppendSeparator()
			menu.Append(popup_AddFile, "Add Existing File")
			menu.AppendSeparator()
			menu.Append(popup_Rename, "Rename")
			menu.Append(popup_Move, "Move")
			menu.Append(popup_Delete, "Delete")
			self.PopupMenu(menu)
			menu.Destroy()
		
		#if (currentMenuItem == self.root or self.GetItemParent(currentMenuItem) == self.root):
		#	return 0

		#if not hasattr(self, "popupID1"):
		#	self.popupDELETE = wx.NewId()
		#	self.Bind(wx.EVT_MENU, self.DeleteFile, id=self.popupDELETE)

		# Show delete menu
		#menu = wx.Menu()
		#menu.Append(self.popupDELETE, "Delete Item")
		#self.PopupMenu(menu)
		#menu.Destroy()
		
		return 0

	def __ContextMenu_PropertiesRepo(self,event):
		self.IDE.SubversionLog("Not Implemented: Repository Properties Dialog.")
		pass
	
	def __ContextMenu_SyncRepo(self,event):
		self.IDE.SubversionLog("Not Implemented: Repository Sync.")
		pass
	
	def __ContextMenu_DeterminePendingFile(self,event):
		self.IDE.SubversionLog("Not Implemented: Determine Pending Changes to File.")
		pass
	
	def __ContextMenu_CommitFile(self,event):
		self.IDE.SubversionLog("Not Implemented: Commit file changes to repo manually.")
		pass
	
	def __ContextMenu_RevertFile(self,event):
		self.IDE.SubversionLog("Not Implemented: Revert file to the repository version.")
		pass
	
	def __ContextMenu_DeleteFile(self,event):
		currentMenuItem = self.GetSelection()
		if (self.CheckIsFileOpenByTreeNode(currentMenuItem)):
			dlg = wx.MessageDialog(self.IDE, 'Please close the file before attempting to delete it.',
									'Unable to Delete File',
									wx.OK | wx.ICON_INFORMATION
									#wx.YES_NO | wx.NO_DEFAULT | wx.CANCEL | wx.ICON_INFORMATION
									)
			dlg.ShowModal()
			dlg.Destroy()
			return 0
		path = self.GetPyData(currentMenuItem)
		dlg = wx.MessageDialog(self.IDE, 'Are you sure you want to delete ' + os.path.basename(path) + ' from the ' + self.ProjectSettings['RepositoryName'] + ' repository?',
									'Delete File?',
									#wx.OK | wx.ICON_INFORMATION
									wx.YES_NO | wx.NO_DEFAULT# | wx.CANCEL | wx.ICON_INFORMATION
									)
		if (dlg.ShowModal() == wx.ID_YES):
			self.SVNCurrentAction = "DeleteFile"
			self.__repo_delete_file = path # store this for repo success, when we need to delete the local file
			self.__repo_delete_node = currentMenuItem 
			self.IDE.SubversionLog("Deleting " + os.path.basename(path) + " in repository...")
			try:
				self.SVNClient.remove(path)
			except:
				dlg = wx.MessageDialog(self.IDE, 'The file could not be deleted.  Make sure that you have saved the latest copy to the repository first, before trying to delete the file.',
									'Unable to Delete File',
									wx.OK | wx.ICON_INFORMATION
									#wx.YES_NO | wx.NO_DEFAULT | wx.CANCEL | wx.ICON_INFORMATION
									)
				dlg.ShowModal()
				dlg.Destroy()
				return 0
			self.SVNClient.checkin([path],"Removed file via SubPython")
		dlg.Destroy()
	
	def __ContextMenu_RenameFile(self,event):
		currentMenuItem = self.GetSelection()
		if (self.CheckIsFileOpenByTreeNode(currentMenuItem)):
			dlg = wx.MessageDialog(self.IDE, 'Please close the file before attempting to rename it.',
									'Unable to Rename File',
									wx.OK | wx.ICON_INFORMATION
									#wx.YES_NO | wx.NO_DEFAULT | wx.CANCEL | wx.ICON_INFORMATION
									)
			dlg.ShowModal()
			dlg.Destroy()
			return 0
		path = self.GetPyData(currentMenuItem)
		dlg = wx.TextEntryDialog(
				self.IDE, 'Enter the new filename for ' + os.path.basename(path),
				'Rename File', os.path.basename(path))

		if (dlg.ShowModal() == wx.ID_OK):
			self.SVNCurrentAction = "RenameFile"
			self.__repo_rename_node = currentMenuItem
			dest = os.path.join(path[:len(path)-len(dlg.GetValue())],dlg.GetValue())
			self.__repo_rename_destname = os.path.basename(dest)
			self.IDE.SubversionLog("Renaming " + os.path.basename(path) + " to " + os.path.basename(dest) + " in repository...")
			try:
				self.SVNClient.move(path,dest)
			except:
				dlg = wx.MessageDialog(self.IDE, 'The file could not be renamed.  Make sure that you have saved the latest copy to the repository first and the new filename is valid before trying to rename the file.',
									'Unable to Rename File',
									wx.OK | wx.ICON_INFORMATION
									#wx.YES_NO | wx.NO_DEFAULT | wx.CANCEL | wx.ICON_INFORMATION
									)
				dlg.ShowModal()
				dlg.Destroy()
				return 0
			self.SVNClient.checkin([path,dest],"Renamed file via SubPython")
		dlg.Destroy()
	
	def __ContextMenu_MoveFile(self,event):
		currentMenuItem = self.GetSelection()
		if (self.CheckIsFileOpenByTreeNode(currentMenuItem)):
			dlg = wx.MessageDialog(self.IDE, 'Please close the file before attempting to move it.',
									'Unable to Move File',
									wx.OK | wx.ICON_INFORMATION
									#wx.YES_NO | wx.NO_DEFAULT | wx.CANCEL | wx.ICON_INFORMATION
									)
			dlg.ShowModal()
			dlg.Destroy()
			return 0
		path = self.GetPyData(currentMenuItem)
		dlg = wx.DirDialog(self.IDE, "Choose a directory (it must be a subdirectory of the checkout folder):",
							os.path.join(self.ProjectPath,"checkout"),
							style=wx.DD_DEFAULT_STYLE | wx.DD_DIR_MUST_EXIST
							)

		if (dlg.ShowModal() == wx.ID_OK):
			self.SVNCurrentAction = "MoveFile"
			self.__repo_move_delnode = currentMenuItem
			self.__repo_move_text = self.GetItemText(currentMenuItem)
			self.__repo_move_path = os.path.join(dlg.GetPath(),os.path.basename(path))
			srcfldr = path[:len(path)-len(os.path.basename(path))-1]
			destfldr = dlg.GetPath()
			
			if (destfldr.count(self.ProjectPath) == 0):
				# It is not a subdirectory of the ProjectPath
				dlg = wx.MessageDialog(self.IDE, 'The destination folder must be underneath ' + self.ProjectPath,
									'Unable to Move File',
									wx.OK | wx.ICON_INFORMATION
									#wx.YES_NO | wx.NO_DEFAULT | wx.CANCEL | wx.ICON_INFORMATION
									)
				dlg.ShowModal()
				dlg.Destroy()
				return 0
			if (destfldr == srcfldr):
				self.IDE.SubversionLog("No move required.")
				return 0
			
			try:
				if (destfldr[len(os.path.join(self.ProjectPath,"checkout"))+1:] == ""):
					self.__repo_rename_destparentnode = self.root
				else:
					self.__repo_rename_destparentnode = self.ProjectDirectories[destfldr[len(os.path.join(self.ProjectPath,"checkout"))+1:]]
			except:
				dlg = wx.MessageDialog(self.IDE, 'Unable to locate the directory node in the project tree list to move this file node into.',
									'Unable to Move File',
									wx.OK | wx.ICON_INFORMATION
									#wx.YES_NO | wx.NO_DEFAULT | wx.CANCEL | wx.ICON_INFORMATION
									)
				dlg.ShowModal()
				dlg.Destroy()
				return 0
			self.IDE.SubversionLog("Moving " + os.path.basename(path) + " from " + srcfldr + " to " + destfldr + " in repository...")
			try:
				self.SVNClient.move(path,os.path.join(destfldr,os.path.basename(path)))
			except:
				dlg = wx.MessageDialog(self.IDE, 'The file could not be moved.  Make sure that you have saved the latest copy to the repository first and the new directory is valid before trying to move the file.',
									'Unable to Move File',
									wx.OK | wx.ICON_INFORMATION
									#wx.YES_NO | wx.NO_DEFAULT | wx.CANCEL | wx.ICON_INFORMATION
									)
				dlg.ShowModal()
				dlg.Destroy()
				return 0
			self.SVNClient.checkin([path,os.path.join(destfldr,os.path.basename(path))],"Moved file via SubPython")
		dlg.Destroy()
	
	def __ContextMenu_LockFile(self,event):
		self.IDE.SubversionLog("Not Implemented: Lock file.")
		pass
	
	def __ContextMenu_UnlockFile(self,event):
		self.IDE.SubversionLog("Not Implemented: Unlock file.")
		pass
	
	def __ContextMenu_DeterminePendingFolder(self,event):
		self.IDE.SubversionLog("Not Implemented: Determine Pending Changes to Folder.")
		pass
	
	def __ContextMenu_RefreshDirectoryFolder(self,event):
		self.IDE.SubversionLog("Not Implemented: Refresh Directory Listing.")
		pass
	
	def __ContextMenu_AddFileFolder(self,event):
		self.IDE.SubversionLog("Not Implemented: Add External File.")
		pass
	
	def __ContextMenu_DeleteFolder(self,event):
		self.IDE.SubversionLog("Not Implemented: Delete Folder.")
		pass
	
	def __ContextMenu_RenameFolder(self,event):
		self.IDE.SubversionLog("Not Implemented: Rename Folder.")
		pass
	
	def __ContextMenu_MoveFolder(self,event):
		self.IDE.SubversionLog("Not Implemented: Move Folder.")
		pass

	def __DeleteFile(self, currentMenuItem):
		if (self.GetItemParent(currentMenuItem) != self.Tree_ScriptList and self.GetItemParent(currentMenuItem) != self.Tree_ExtraList):
			return 0
		
		if (self.GetItemText(currentMenuItem) != ""):
			data_path = os.path.join(self.base_location,self.data_location)
			if (os.path.exists(data_path + "/" + self.GetItemText(currentMenuItem))):
				try:
					os.remove(data_path + "/" + self.GetItemText(currentMenuItem))
				except:
					NooneCares = True

		if (self.GetItemParent(currentMenuItem) == self.Tree_ScriptList):
			self.Data_ScriptList.remove(currentMenuItem)
		if (self.GetItemParent(currentMenuItem) == self.Tree_ExtraList):
			self.Data_ExtraList.remove(currentMenuItem)
		
		self.Delete(currentMenuItem)
		self.__SaveProject()
	
##				self.projectman.SetItemImage(handler.scriptlist[:], self.fldridx, wx.TreeItemIcon_Normal)
##				#self.last_name_saved = path
##				self.statusbar.SetStatusText('Successfully opened ' + path, 0)
##			except IOError, error:
##				dlg = wx.MessageDialog(self.IDE, 'Error opening file ' + str(error))
##				dlg.ShowModal()
##			except UnicodeDecodeError, error:
##				dlg = wx.MessageDialog(self.IDE, 'Error opening file ' + str(error))
##				dlg.ShowModal()
##
##			self.projectman.SetItemImage(self.handler.scriptlist, self.filerksm, wx.TreeItemIcon_Normal)
